/**
 * Created by Truman on 2017/3/21.
 */

var xElevator = function (config) {
	
	var defaults = {
		world: '.xelevator',
		building : '.building',
		car: '.car',
		speed: 30,
		max: 10,
		floors: 10
	};
	var options = $.extend(true, {}, defaults, config);
	
	var world = $(options.world);
	
	var xMan = function (param) {
		var man = {
			element: undefined,
			from: param.from,
			to: param.to,
			initialize: function(){
				man.element = $('<div class="xman"><i class="fa fa-user"></i></div>');
			}
		};
		man.initialize();
		return man;
	};
	
	var xFloor = function (element) {
		var floor = {
			element: element,
			waitline: undefined,
			no: undefined,
			persons: [],
			up: false,
			down: false,
			altitude: undefined,
			initialize: function () {
				floor.element.append('<div class="indicator"><i class="fa fa-toggle-up"></i><br/><i class="fa fa-toggle-down"></i></div>');
				var $waitline = $('<div class="wait-line"></div>');
				floor.element.append($waitline);
				floor.waitline = $waitline;
				
				floor.altitude = floor.element.position().top + floor.element.outerHeight();
			},
			newPerson: function (param) {
				var man = new xMan(param);
				floor.element.append(man.element);
				floor.enroll(man);
				floor.persons.push(man);
				
				if(man.from < man.to){
					floor.up = true;
					
				}else if(man.from < man.to){
					floor.down = true;
				}
			},
			enroll: function (man) {
				if(floor.persons.length < 1){
					man.element.css({
						left: (floor.waitline.position().left + floor.waitline.outerWidth(true)) + 'px'
					});
				}else{
					man.element.css({
						left: (floor.persons[floor.persons.length - 1].element.position().left + floor.persons[floor.persons.length - 1].element.outerWidth(true)) + 'px'
					});
				}
			}
		};
		
		floor.initialize();
		return floor;
	};
	
	function dequeue(queue, node){
		for(var i = 0 ; i < queue.length; i++){
			if(queue[i] == node){
				queue.splice(i, 1);
			}
		}
	}
	
	var building = {
		element: world.find('.building'),
		floors: [],
		initialize: function () {
			for(var i = 0; i < options.floors; i++){
				var $floor = $('<li class="floor"></li>');
				building.element.prepend($floor);
				$floor.append('<div class="sign">'+ (i + 1) +'</div>');
				
				building.floors.push(new xFloor($floor));
			}
		},
		lighten: function (idx, flag) {
			//console.log(idx);
			//console.log(building.floors);
			building.floors[idx].element.toggleClass('active', flag);
		},
		call: function(data){
			if(data.from == data.to) return false;
			
			building.floors[data.from].newPerson(data);
			
			return true;
		}
	};
	
	var car = {
		element: world.find('.car'),
		running: false,
		waiting: false,
		height: undefined,
		direction : 0,
		current: 0,
		persons: [],
		queue: [],
		initialize: function () {
			car.height = car.element.outerHeight();
			for(var i = 0; i < building.floors.length; i++){
				car.queue.push(false);
			}
		},
		run: function () {
			car.running = true;
			car.listen();
		},
		stop: function () {
			car.running = false;
		},
		listen: function(){
			console.log('listening...');
			
			if(car.waiting){
				setTimeout(car.listen, options.speed * 3);
				return;
			}
			
			if(car.direction != 0){
				car.move();
				return;
			}
			
			for(var i = 0; i < car.queue; i++){
				if(car.queue[i]){
					car.setDirection(car.current, i);
					car.move();
					return;
				}
			}
			
			for(var i=0; i < building.floors.length; i++){
				if(building.floors[i].up || building.floors[i].down){
					car.setDirection(car.current, i);
					car.move();
					return;
				}
			}
			
			if(car.running)
				setTimeout(car.listen, options.speed);
		},
		setDirection: function (from, to) {
			if(to > from){
				car.direction = 1;
			}else if(to < from){
				car.direction = -1;
			}
			
			console.log(from);
			console.log(to);
			console.log('setDirection: '+ car.direction);
		},
		move: function () {
			var current = car.checkFloor(car.element.position().top + car.height);
			if(current >= 0){
				building.lighten(current, true);
				
				if(car.checkOpen()){
					car.waiting = true;
				}
				
				car.listen();
			}else{
				building.lighten(car.current, false);
				
				car.element.css({
					top: (car.element.position().top - (1 * car.direction)) + 'px'
				});
				
				if(car.running){
					setTimeout(car.move, options.speed, car.direction);
				}
			}
		},
		checkFloor: function (position) {
			for(var i = 0; i < building.floors.length; i++){
				if(building.floors[i].altitude == position){
					return i;
				}
			}
			
			return -1;
		},
		checkOpen: function () {
			for(var i = 0; i < car.queue.length; i++){
				if(car.queue[i] && i == car.current){
					return true;
				}
			}
			
			for(var i = 0; i < building.floors.length; i++){
				if((car.direction >= 0 && building.floors[i].up)
				|| (car.direction <= 0 && building.floors[i].down)){
					return true;
				}
			}
			
			return false;
		},
		walkin: function(idx, man){
			var left = car.element.position().left + 3;
			if(car.persons.length > 0){
				left = car.persons[car.persons.length - 1].element.position().left + car.persons[car.persons.length - 1].element.outerWidth(true);
			}
			
			if(left == man.element.position().left) {
				dequeue(building.floors[idx].persons, man);
				car.persons.push(man);
				return;
			}
			
			man.element.css({
				left: (man.element.position().left * (left < man.element.position().left ? -1 : 1)) + 'px'
			});
			
			setTimeout(car.walkin, options.speed, idx, man);
		}
	};
	
	var xe = {
		initialize: function () {
			building.initialize();
			car.initialize();
		},
		run: car.run,
		stop: car.stop,
		call: building.call
	};
	
	xe.initialize();
	return xe;
}